﻿using Dapper;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Net.PeerToPeer.Collaboration;
using System.Text;
using System.Threading.Tasks;

namespace Asion.Dapper
{
    /// <summary>
    /// 默认连接创建工厂类
    /// </summary>
    public class DbConnectionFactory : IDbConnectionFactory
    {
        private static IDictionary<string, DbConfiguration> connections = new ConcurrentDictionary<string, DbConfiguration>();

        public DbConnectionFactory()
        {

        }

        public DbConnectionFactory(DbConfiguration dbConfiguration)
        {
            Initialize(new List<DbConfiguration>() { dbConfiguration });
        }

        public DbConnectionFactory(IList<DbConfiguration> dbConfigurations)
        {
            Initialize(dbConfigurations);
        }

        public IDbConnection CreateConnection(string name)
        {
            return GetConnection(name);
        }


        public int GetCount()
        {
            return connections.Count;
        }

        /// <summary>
        /// init
        /// </summary>
        public void Initialize(IEnumerable<DbConfiguration> dbConfigurations)
        {
            if (!dbConfigurations.Any())
            {
                throw new ArgumentNullException("DbConfiguration is not settings");
            }
            //判断是否有configid作为区分

            foreach (var item in dbConfigurations)
            {
                ConnectionManageAdd(item, dbConfigurations.Count() == 1);
            }
        }


        /// <summary>
        /// init
        /// </summary>
        public void Initialize(DbConfiguration dbConfigurations)
        {

            Initialize(new List<DbConfiguration>() { dbConfigurations });
        }

        /// <summary>
        /// add conection
        /// </summary>
        private void ConnectionManageAdd(DbConfiguration dbConfiguration, bool isSingleDb)
        {
            var id = dbConfiguration.Id.ToLower();
            if (isSingleDb)
            {
                DapperConfiguration.default_connection = id;
            }
            if (!connections.ContainsKey(id))
            {
                connections.Add(id, dbConfiguration);
            }

        }

        public IDbConnection GetMasterConnection()
        {
            return GetConnection(DapperConfiguration.default_connection);
        }

        private IDbConnection GetConnection(string name)
        {
            name = name.ToLower();
            if (connections.TryGetValue(name, out DbConfiguration dbConfiguration))
            {
                if (dbConfiguration.DbType == DatabaseType.SQLServer)
                {
                    return new SqlServerDbProvider().GetConnection(dbConfiguration.ConnectionString);
                }
                if (dbConfiguration.DbType == DatabaseType.MySQL)
                {
                    return new MySqlDbProvider().GetConnection(dbConfiguration.ConnectionString);
                }
            }
            throw new ArgumentNullException();
        }


        public DatabaseType GetDbType(string name)
        {
            name = name.ToLower();
            if (connections.TryGetValue(name, out DbConfiguration dbConfiguration))
            {
                return dbConfiguration.DbType;
            }
            throw new ArgumentNullException();
        }

        public void ChangeMasterConnection(string name)
        {
            if (!connections.ContainsKey(name))
            {
                throw new ArgumentNullException($" the {name}  is  not find");
            }

            DapperConfiguration.default_connection = name;
        }

        public void AddDbConfiguration(DbConfiguration dbConfigurations)
        {
            ConnectionManageAdd(dbConfigurations,true);
        }

        public void AddDbConfigurations(IEnumerable<DbConfiguration> dbConfigurations)
        {
            if (!dbConfigurations.Any())
            {
                throw new ArgumentNullException("DbConfiguration is not settings");
            }
            //判断是否有configid作为区分
            foreach (var item in dbConfigurations)
            {

                ConnectionManageAdd(item, dbConfigurations.Count() == 1);
            }


        }
    }
}
